<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

    <script>
        // https://www.netlify.com/blog/2019/03/11/deep-dive-how-do-react-hooks-really-work/
        // Example 4
        const MyReact = (function () {
            let Hook = {
                hooks: [],
                currentHook: 0
            }
            window.Hook = Hook
            // let hooks = [],
            //     currentHook = 0 // array of hooks, and an iterator!
            return {
                render(Component) {
                    let {hooks,currentHook} = Hook
                    const Comp = Component() // run effects
                    Comp.render()
                    Hook.currentHook = 0 // reset for next render
                    return Comp
                },
                useEffect(callback, depArray) {
                    let {hooks,currentHook} = Hook
                    const hasNoDeps = !depArray
                    const deps = hooks[currentHook] // type: array | undefined
                    const hasChangedDeps = deps ? !depArray.every((el, i) => el === deps[i]) : true
                    if (hasNoDeps || hasChangedDeps) {
                        callback()
                        hooks[currentHook] = depArray
                    }
                    Hook.currentHook+=1 // done with this hook
                },
                useState(initialValue) {
                    let {hooks,currentHook} = Hook
                    hooks[currentHook] = hooks[currentHook] || initialValue // type: any
                    const setStateHookIndex = currentHook // for setState's closure!
                    const setState = newState => (hooks[setStateHookIndex] = newState)
                    Hook.currentHook+=1
                    return [hooks[currentHook], setState]
                }
            }
        })()


        // Example 4 continued - in usage
        function Counter() {
            const [count, setCount] = MyReact.useState(0)
            const [text, setText] = MyReact.useState('foo') // 2nd state hook!
            console.warn(count,text)
            MyReact.useEffect(() => {
                // console.log('effect', count, text)
            }, [count, text])
            return {
                click: () => setCount(count + 1),
                type: txt => setText(txt),
                noop: () => setCount(count),
                render: () => console.log('render', {
                    count,
                    text
                })
            }
        }
        function run (){
            let App
            App = MyReact.render(Counter)
            // effect 0 foo
            // render {count: 0, text: 'foo'}
            App.click()
            App = MyReact.render(Counter)
            // effect 1 foo
            // render {count: 1, text: 'foo'}
            App.type('bar')
            App = MyReact.render(Counter)
            // effect 1 bar
            // render {count: 1, text: 'bar'}
            App.noop()
            App = MyReact.render(Counter)
            // // no effect run
            // render {count: 1, text: 'bar'}
            App.click()
            App = MyReact.render(Counter)
            // effect 2 bar
            // render {count: 2, text: 'bar'}        
        }
    </script>
</body>

</html>